package websocket

import (
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"net/http"
	"strings"
)

var acceptKeyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")

func generateAcceptKey(key string) string {
	h := sha1.New()
	h.Write([]byte(key))
	h.Write(acceptKeyGUID)
	return base64.StdEncoding.EncodeToString(h.Sum(nil))
}

func NewWebsocket(writer http.ResponseWriter, request *http.Request) (*Conn, error) {

	if request.Method != "GET" {
		return nil, fmt.Errorf("HTTP必须是GET方法")
	}

	if !httpHeaderContainsValue(request.Header, "Upgrade", "websocket") {
		return nil, fmt.Errorf("必须包含一个Upgrade header字段，它的值必须为websocket")
	}

	// TODO 验证request header

	hijacker, ok := writer.(http.Hijacker)
	if !ok {
		return nil, fmt.Errorf("未实现http.Hijacker")
	}
	netConn, buf, err := hijacker.Hijack()
	if err != nil {
		return nil, err
	}

	var response []byte
	response = append(response, "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "...)
	response = append(response, generateAcceptKey(request.Header.Get("Sec-WebSocket-Key"))...)
	response = append(response, "\r\n"...)

	// TODO 其他header信息
	response = append(response, "\r\n"...)
	if _, err = netConn.Write(response); err != nil {
		netConn.Close()
	}

	c := newConn(netConn, buf.Reader)

	return c, nil
}

func httpHeaderContainsValue(header http.Header, name string, value string) bool {
	v := header.Get(name)
	return strings.EqualFold(v, value)
}
